package com.youkeyi.ddy.cloud.application.system.login.controller;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youkeyi.ddy.cloud.application.system.login.dto.LoginDto;
import com.youkeyi.ddy.cloud.application.system.login.service.LoginService;
import com.youkeyi.ddy.cloud.application.system.login.service.WeChatOfficialService;
import com.youkeyi.ddy.cloud.common.annotation.PassToken;
import com.youkeyi.ddy.cloud.common.api.application.system.login.SystemOfficialLoginFeignService;
import com.youkeyi.ddy.cloud.common.api.application.system.login.dto.OfficialLoginAuthCloudDto;
import com.youkeyi.ddy.cloud.common.api.application.system.login.dto.WxOfficialUserInfoDto;
import com.youkeyi.ddy.cloud.common.api.application.system.login.param.OfficialLoginAuthCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.PublicUserCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.dto.PublicUserListCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.dto.PublicUserListItemCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.param.PublicUserQueryCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.param.PublicUserUpdateCloudParam;
import com.youkeyi.ddy.cloud.common.constant.YoukeyiDdyApplicationSystemConstant;
import com.youkeyi.ddy.cloud.common.context.YoukeyiSystemContext;
import com.youkeyi.ddy.cloud.common.enums.ResponseCodeEnum;
import com.youkeyi.ddy.cloud.common.response.ResponseContent;
import com.youkeyi.ddy.cloud.common.response.ResponseObjectContent;
import com.youkeyi.ddy.cloud.common.utils.RedisUtils;
import com.youkeyi.ddy.cloud.common.utils.SecurityUtils;
import com.youkeyi.ddy.cloud.common.utils.SimpleUUidUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;
import org.springframework.stereotype.Service;
import springfox.documentation.spi.service.contexts.ResponseContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * SystemOfficialLoginController
 *
 * @Author liuxiawang
 * @Date 2024/5/6 4:40 PM
 * @Location shenzhen.china
 */
@Service
public class SystemOfficialLoginController implements SystemOfficialLoginFeignService {

    private static final String OFFICIAL_APP_ID = "wx5589a0e69a84dbef";
    private static final String OFFICIAL_APP_SECRET = "844c5fd085b5fb35641405a790bf94f7";
    private static final String OFFICIAL_PAGE_URL_URI = "https://ddy.yoyejia.com/#/login";

    @Autowired
    private LoginService loginService;
    @Autowired
    private PublicUserCloudService publicUserCloudService;
    @Autowired
    private WeChatOfficialService weChatOfficialService;

    /**
     * scope为snsapi_base：
     * https://open.weixin.qq.com/connect/oauth2/authorize
     * ?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect
     *
     * scope为snsapi_userinfo：
     * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx807d86fb6b3d4fd2&redirect_uri=http%3A%2F%2Fdevelopers.weixin.qq.com&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
     */
    @Override
    @PassToken
    public OfficialLoginAuthCloudDto getPageUrl(OfficialLoginAuthCloudParam param) {
        // https://open.weixin.qq.com/connect/oauth2/authorize
        // ?appid=wx807d86fb6b3d4fd2
        // &redirect_uri=http%3A%2F%2Fdevelopers.weixin.qq.com
        // &response_type=code
        // &scope=snsapi_userinfo
        // &state=STATE
        // #wechat_redirect
        String redirectUri="";
         if (null == param || StringUtils.isBlank(param.getRedirectUrl())) {
             redirectUri=OFFICIAL_PAGE_URL_URI;
         }else {
             redirectUri = param.getRedirectUrl();
         }

        String state= UUID.randomUUID().toString();//授权状态标记值，前后端唯一标记
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize";
        OfficialLoginAuthCloudDto dto = new OfficialLoginAuthCloudDto();
        dto.setUrl(
                String.format("%s?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=%s#wechat_redirect",
                        url,
                        OFFICIAL_APP_ID,
                        redirectUri,
                        state
                )
        );
        dto.setKey(state);//将前后端唯一标记值回传会前段
        dto.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());

        //将状态state 存进 redis
        SecurityUtils.SecurityKey securityKey;
        try {
            securityKey = SecurityUtils.getKey(String.format("%s%s", "LOGIN_CODE", String.valueOf(System.currentTimeMillis())));
        } catch (Exception e) {
            e.printStackTrace();
            dto.setErrorMessage("获取密钥对失败");
            return dto;
        }
        Map<String, String> authStateMap=new HashMap<>();
        authStateMap.put("authStateUUID",state);
//        authStateMap.put("authState","false");
//        authStateMap.put("code","");
        try {
            // 存入redis
            RedisUtils.addHashMapToJedis(YoukeyiDdyApplicationSystemConstant.AUTH_LOGIN_REDIS_DB_INDEX, state, authStateMap, YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_CACHE_SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
            dto.setErrorMessage("存入Redis 失败");
            return dto;
        }

        return dto;
    }

    @Override
    @Description("轮询访问授权状态")
    @PassToken
    public OfficialLoginAuthCloudDto checkAuthorizationStatus(String state){
        OfficialLoginAuthCloudDto dto=new OfficialLoginAuthCloudDto();

        if (StringUtils.isBlank(state)) {
            dto.setErrorMessage("state不存在，请联系管理员");
            return dto;
        }
        Map<String, String> authStateMap;
        try {
            authStateMap = new HashMap<>(RedisUtils.getHashMapFromJedis(YoukeyiDdyApplicationSystemConstant.AUTH_LOGIN_REDIS_DB_INDEX, state));
        } catch (Exception e) {
            e.printStackTrace();
            dto.setErrorMessage("获取state失败");
            return dto;
        }

        String code;
        String authState;
        code=authStateMap.get("code");
        authState=authStateMap.get("authState");
        dto.setAuthState(authState);
        dto.setAuthCode(code);
        return dto;
    }


    @Override
    @Description("微信公众号回调函数")
    @PassToken
    public ResponseContent handleCallback(String code,String state){
        ResponseContent rc = new ResponseContent();
        Map<String, String> authStateMap;
        try {
            authStateMap = new HashMap<>(RedisUtils.getHashMapFromJedis(YoukeyiDdyApplicationSystemConstant.AUTH_LOGIN_REDIS_DB_INDEX, state));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            RedisUtils.updateHashMapToJedis(YoukeyiDdyApplicationSystemConstant.AUTH_LOGIN_REDIS_DB_INDEX, state,
                    "authState", 1, "authState", "true"
            );
            RedisUtils.updateHashMapToJedis(YoukeyiDdyApplicationSystemConstant.AUTH_LOGIN_REDIS_DB_INDEX, state,
                    "code", 1, "code", code
            );
        }catch (Exception e){
            e.printStackTrace();
        }

        rc.setSuccessMessage("回调成功:state:"+state);
        rc.setKey(code);
        return rc;

    }
    @Override
    @Description("公众号扫码获取uniondid、openid与用户phone 绑定")
    @PassToken
    public ResponseContent bindUserByPhoneAndOpenidAndUnionId(String phone,String unionId,String openId){
        ResponseContent rt=new ResponseContent();
        rt.setSuccessMessage("绑定成功！");
        PublicUserQueryCloudParam userQueryCloudParam = new PublicUserQueryCloudParam();
        userQueryCloudParam.setPhones(Collections.singletonList(phone));
        PublicUserListCloudDto userDtos = publicUserCloudService.query(userQueryCloudParam);
        if (userDtos == null || CollectionUtils.isEmpty(userDtos.getRows())) {
            rt.setErrorMessage("未知的phone");
            return rt;
        }
        // 修改user表的小程序的open id跟微信union id
        PublicUserListItemCloudDto dto=userDtos.getRows().get(0);
        if (StringUtils.isNotBlank(dto.getUserPrimaryKey())
                && StringUtils.isNotBlank(openId)) {
            PublicUserUpdateCloudParam userUpdateCloudParam = new PublicUserUpdateCloudParam();
            userUpdateCloudParam.setUserPrimaryKey(dto.getUserPrimaryKey());
            userUpdateCloudParam.setOfficialOpenId(openId);
            userUpdateCloudParam.setUnionId(unionId);
            userUpdateCloudParam.setIsRoot(dto.getIsRoot());
            userUpdateCloudParam.setUpdateUserKey(YoukeyiSystemContext.getUserPrimaryKey());
            userUpdateCloudParam.setUpdateUserName(YoukeyiSystemContext.getUserName());
            ResponseContent  result= publicUserCloudService.update(userUpdateCloudParam);
            return  result;
        }
        return rt;
    }

    @Description("获取用户信息")
    private WxOfficialUserInfoDto getUserInfo(String accessToken,String openId){
        String urlGetUserInfo = "https://api.weixin.qq.com/sns/userinfo?"+
                "access_token="+accessToken+
                "&openid="+openId+
                "&lang=zh_CN" ;

        String res = HttpUtil.get(urlGetUserInfo);
        WxOfficialUserInfoDto  dto = JSONObject.parseObject(res,WxOfficialUserInfoDto.class);

        return dto;
    }

    @Override
    @PassToken
    public ResponseObjectContent getToken(OfficialLoginAuthCloudParam param) {
        ResponseObjectContent<LoginDto> rc = new ResponseObjectContent<>();
        if (null == param || StringUtils.isBlank(param.getCode())) {
            rc.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return rc;
        }

        String urlGetToken = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "grant_type=authorization_code" +
                "&appid="+ OFFICIAL_APP_ID +
                "&secret="+ OFFICIAL_APP_SECRET +
                "&code=" + param.getCode();
        String res = HttpUtil.get(urlGetToken);
        JSONObject jsonObject = JSONObject.parseObject(res);
        if (null == jsonObject) {
            rc.setErrorMessage("访问微信授权接口失败");
            return rc;
        }

        String accessToken = jsonObject.getString("access_token");
      //  String unionId = jsonObject.getString("unionid");
        String openId = jsonObject.getString("openid");

        WxOfficialUserInfoDto userInfoDto=getUserInfo(accessToken,openId);//获取用户信息里面拿取 unionid  需要挂载在微信开放平台下 才有 unionid
        String unionId=userInfoDto.getUnionid();
//        if (null == unionId||"".equals(unionId)) {
//            rc.setErrorMessage("访问微信授权接口失败,没有获取到UnionId");
//            return rc;
//        }
        String token = SimpleUUidUtils.getUuid();
        rc.setKey(unionId+"&"+openId);

        PublicUserQueryCloudParam userQueryCloudParam = new PublicUserQueryCloudParam();
        userQueryCloudParam.setUnionIds(Collections.singletonList(unionId));
        userQueryCloudParam.setOfficialOpenIds(Collections.singletonList(openId));
        PublicUserListCloudDto userDtos = publicUserCloudService.query(userQueryCloudParam);
        if (userDtos == null || CollectionUtils.isEmpty(userDtos.getRows())) {
            rc.setErrorMessage("未知的unionid");
            return rc;
        }

        PublicUserListItemCloudDto user = userDtos.getRows().get(0);
        LoginDto loginDto = loginService.login(user.getPhone(), "", token, "official");
        rc.setData(loginDto);
        rc.setSuccess(loginDto.isSuccess());
        rc.setMessage(loginDto.getMessage());

        // 修改user表的小程序的open id跟微信union id
        if (StringUtils.isNotBlank(loginDto.getUserPrimaryKey()) && StringUtils.isNotBlank(openId)) {
            PublicUserUpdateCloudParam userUpdateCloudParam = new PublicUserUpdateCloudParam();
            userUpdateCloudParam.setUserPrimaryKey(loginDto.getUserPrimaryKey());
            userUpdateCloudParam.setOfficialOpenId(openId);
            userUpdateCloudParam.setUpdateUserKey(YoukeyiSystemContext.getUserPrimaryKey());
            userUpdateCloudParam.setUpdateUserName(YoukeyiSystemContext.getUserName());
            userUpdateCloudParam.setIsRoot(loginDto.getIsRoot());
            publicUserCloudService.update(userUpdateCloudParam);
        }
        rc.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());
        return rc;
    }

    @Override
    public ResponseContent logout(HttpServletRequest request, HttpServletResponse response) {
        ResponseContent rc = new ResponseContent();
        String token = request.getHeader(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_TOKEN_KEY);
        try {
            RedisUtils.delKeyFromJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, token);
            rc.setSuccessMessage("登出成功");
        } catch (Exception e) {
            e.printStackTrace();
            rc.setErrorMessage("登出失败");
        }
        return rc;
    }


    @Override
    @Description("微信公众号签名获取")
    @PassToken
    public ResponseObjectContent getWeChatOfficialConfig(String url) {
        return weChatOfficialService.generateWeChatConfig(url);
    }
}
